package munci.old.learn;

import munci.old.java.Signature;
import munci.old.know.Env;
import munci.old.know.Stack;
import munci.old.know.Dictionary.Bookmark;
import munci.old.know.words.MetaWord;
import munci.old.know.words.MethodWord;
import munci.old.know.words.Word;
import munci.old.use.Tokens;
import munci.read.Token;


public class Basics {
	
	public static final Word[] WORDS =
			MetaWord.all(MethodWord.all(new Word.Book(Basics.class))).toArray();

	@MethodWord.Name("bye") public static void bye() {
		Runtime.getRuntime().exit(0);
	}

	@MethodWord.Name("line") public static void line() {
		System.out.println();
	}

	@MetaWord.Name("dup") public static void dup(Env env) {
		env.stack.dup();
	}

	@MetaWord.Name("pop") public static void pop(Env env) {
		env.stack.pop();
	}
	
	@MetaWord.Name("swap") public static void swap(Env env) {
		env.stack.swap();
	}

	@MetaWord.Name("over") public static void up(Env env) {
		env.stack.over((Integer) env.stack.pop());
	}

	@MetaWord.Name("[") public static boolean now(Env env) {
		if (!env.compiling()) return false;
		env.setCompiling(false);
		return true;
	}
	
	@MetaWord.Name("]") public static boolean later(Env env) {
		if (env.compiling()) return false;
		env.setCompiling(true);
		return true;
	}
	
	@MetaWord.Name("`") public static void tokens(Env env) {
		Tokens toks = new Tokens();
		
		while (!env.token().image().equals("`")) {
			toks.add(env.token());
			env.nextToken();
		}
		env.nextToken();
		env.stack.push(toks, Tokens.class);
	}
	
	
	@MethodWord.Name("{") public static Tokens quote() {
		Tokens toks = new Tokens();
		Env env = Env.get();
		
		int par = 1;
		for (;;) {
			Token tok = env.token();
			env.nextToken();
			if (tok.image().equals("}")) {
				par--;
				if (par == 0) break;
			} else if (tok.image().equals("{")) par++;
			toks.add(tok);
		}
		return toks;
	}

//	@MetaWord.Name("{") public static void quote(final Env env) {
//		final Bookmark mark = env.dict.bookmark();
//		final boolean compiling = env.compiling();
//		
//		Word end = new Word("}") {
//			public boolean execute(Env env) {
//				mark.forget();
//				env.setCompiling(compiling);
//				Tokens toks = new Tokens().add("{");
//				concat(env.stack, toks);
//				env.stack.push(toks.add("}"), Tokens.class);
//				return true;
//			}
//			void concat(Stack stack, Tokens toks) {
//				Object top = stack.pop();
//				if (top == this) return;
//				concat(stack, toks);
//				toks.addAll((Tokens) top);
//				if (!toks.endsWith("}")) toks.add(";");
//			}
//			@Override public String toString() {return "{";}
//		};
//		env.stack.push(end, Word.class);
//		env.dict.learn(end);
//		env.setCompiling(true);
//	}
	
	@MetaWord.Name("(") public static void list(Env env) {
		final Bookmark mark = env.dict.bookmark();
		Word end = new Word(")") {
			public boolean execute(Env env) {
				mark.forget();
				Stack stack = new Stack();
				for (;;) {
					Class<?> type = env.stack.peekClass(0);
					Object top = env.stack.pop();
					if (top == this) {
						env.stack.push(stack, Stack.class);
						return true;
					}
					stack.pushUnder(top, type);
				}
			}
			@Override public String toString() {return "(";}
		};
		env.stack.push(end, Word.class);
		env.dict.learn(end);
	}
	
	@MethodWord.Name("--") public static Object returns() {
		return Signature.RETURNS;
	}
	
	@MethodWord.Name("signature") public static Tokens signature(Stack stack, CharSequence name) {
		return new Signature(stack).toJava(name.toString());
	}
	
	@MethodWord.Name("$property") public static String property(String name) {
		return System.getProperty(name);
	}
}
